#include "hidefiles.h"
#include "ui_hidefiles.h"
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
#include <QProcess>
#include <QDir>
#include <QFileDialog>
#include <QStringListModel>
#include <QModelIndex>
#include <QProgressDialog>
#include <QMessageBox>

QStringList g_File_Pathes;
QFile g_DataBaseFile("DataBase");
QFile g_DeviceFile("DeviceFile");
QProcess *console= new QProcess();
qint32 g_FindByMaskFlag=0;
QStringListModel g_Pathes_Model;


HideFiles::HideFiles(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::HideFiles)
{
    ui->setupUi(this);
}

HideFiles::~HideFiles()
{
    delete ui;
}
void HideFiles::ReadFile()
{
    g_DataBaseFile.open(QIODevice::ReadWrite | QIODevice::Text);

    QTextStream DataBaseStream(&g_DataBaseFile);

    QString File_Path;

    while ((File_Path=DataBaseStream.readLine())!=NULL)
    {
        g_File_Pathes.insert(0,File_Path);
    }

    WriteFile();

    g_DataBaseFile.close();
    ui->DirPath->hide();
    ui->DirLable->hide();
    ui->MaskEdit->hide();
    ui->MaskLable->hide();

    if (g_File_Pathes.empty())
    {
        ui->ShowAll_button->setDisabled(1);
        ui->HideAll->setDisabled(1);
        ui->Hide_Button->setEnabled(1);
        ui->Show_Button->setDisabled(1);
    }
    else
    {
        ui->ShowAll_button->setEnabled(1);
        ui->HideAll->setDisabled(1);
        ui->Hide_Button->setEnabled(1);
        ui->Show_Button->setEnabled(1);
    }

    g_Pathes_Model.setStringList(g_File_Pathes);
    ui->PatheslistView->setModel(&g_Pathes_Model);
    ui->PatheslistView->show();

    g_DataBaseFile.remove();
}

void HideFiles::on_Hide_Button_clicked()
{

    if (ui->DirMode->isChecked())
    {
        if (ui->DirPath->text().endsWith("/"))
        {
            ui->DirPath->text().resize(ui->DirPath->text().length()-1);
        }
        if (CheckSysFile(ui->DirPath->text())==0)
        {
            goto finish;
        }

        ScanDir(ui->DirPath->text(),ui->MaskEdit->text());        

        if (g_FindByMaskFlag>0)
        {
            ui->label->setText("Some files were successfully hidden");
            ui->ShowAll_button->setEnabled(1);
            ui->Hide_Button->setEnabled(1);
            ui->Show_Button->setEnabled(1);
        }
        else
        {
             ui->label->setText("File path or mask is invalid");
        }

        g_FindByMaskFlag=0;

    }
    else
    {
        if (CheckSysFile(ui->lineEdit->text())==0)
        {
            goto finish;
        }

        if (QFile::exists(ui->lineEdit->text())==false)
        {
            ui->label->setText("File path "+ui->lineEdit->text()+" is invalid.");
            goto finish;
        }

        g_File_Pathes.insert(0,ui->lineEdit->text());

        ui->label->setText("File "+ui->lineEdit->text()+" is hidden.");

        ui->ShowAll_button->setEnabled(1);
        ui->Hide_Button->setEnabled(1);
        ui->Show_Button->setEnabled(1);

    }
    WriteFile();

    finish:
    g_Pathes_Model.setStringList(g_File_Pathes);
    ui->PatheslistView->setModel(&g_Pathes_Model);
    ui->PatheslistView->show();
}

void HideFiles::on_Show_Button_clicked()
{
    if (ui->DirMode->isChecked())
    {
        if (ui->DirPath->text().endsWith("/"))
        {
            ui->DirPath->text().resize(ui->DirPath->text().length()-1);
        }

        ShowByMask(ui->DirPath->text(),ui->MaskEdit->text());

        goto Show;
    }


    if (g_File_Pathes.contains(ui->lineEdit->text())==false)
    {
        ui->label->setText("File path "+ui->lineEdit->text()+" is invalid.");
        goto finish;
    }

    g_File_Pathes.removeAt(g_File_Pathes.indexOf(ui->lineEdit->text()));

    ui->label->setText("You can see file "+ui->lineEdit->text()+" now");

    Show:
    WriteFile ();

    if (g_File_Pathes.empty())
    {
        ui->ShowAll_button->setDisabled(1);
        ui->HideAll->setDisabled(1);
        ui->Hide_Button->setEnabled(1);
        ui->Show_Button->setDisabled(1);
    }

    finish:
    g_Pathes_Model.setStringList(g_File_Pathes);
    ui->PatheslistView->setModel(&g_Pathes_Model);
    ui->PatheslistView->show();
}

void HideFiles::closeEvent(QCloseEvent*)
{
    QStringList::const_iterator i=g_File_Pathes.begin();

    g_DataBaseFile.open(QIODevice::ReadWrite | QIODevice::Text);

    QTextStream DataBaseFileStream(&g_DataBaseFile);

    while(i!=g_File_Pathes.end())
    {
        DataBaseFileStream<<*i;
        DataBaseFileStream<<"\n";
        ++i;
    }

    g_DataBaseFile.close();

    console->startDetached ("rmmod HideFiles.ko");

    g_DeviceFile.remove();
}

void HideFiles::on_ShowAll_button_clicked()
{
    console->startDetached ("rmmod HideFiles.ko");
    ui->ShowAll_button->setDisabled(1);
    ui->HideAll->setEnabled(1);
    ui->Hide_Button->setDisabled(1);
    ui->Show_Button->setDisabled(1);
}

void HideFiles::on_HideAll_clicked()
{
    WriteFile ();
    ui->ShowAll_button->setEnabled(1);
    ui->HideAll->setDisabled(1);
    ui->Hide_Button->setEnabled(1);
    ui->Show_Button->setEnabled(1);
}

void HideFiles::WriteFile ()
{
    console->startDetached ("rmmod HideFiles.ko");
    sleep(1);
    console->startDetached ("insmod HideFiles.ko");

    QStringList::const_iterator i=g_File_Pathes.begin();

    g_File_Pathes.removeDuplicates();

    g_File_Pathes.sort();

    while(i!=g_File_Pathes.end())
    {
        g_DeviceFile.open(QIODevice::ReadWrite | QIODevice::Text);
        QTextStream DeviceFileStream(&g_DeviceFile);
        DeviceFileStream<<*i<<endl;
        g_DeviceFile.close();

        ++i;
    }

}

QString HideFiles::GetMajorNumber()
{
    QFile Devices("/proc/devices");

    Devices.open(QIODevice::ReadOnly);
    QString Device_Number;

    while ((Device_Number=Devices.readLine())!=NULL)
    {
        if (Device_Number.contains("Hide_Driver"))
        break;
    }
    Devices.close();

    Device_Number.resize(3);

    return Device_Number;
}

void HideFiles::ScanDir (QString ADirname, QString Filter)
{

        if(!ADirname.isEmpty())
        {
                QStringList  tmpDirList;

                QStringList tmpFileList;

                QDir dir(ADirname);

                if(dir.exists()==true)
                {
                    if (ui->includeDirChbx->isChecked())
                    {
                        tmpFileList=dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::NoSort);
                    }
                    else
                    {
                        tmpFileList=dir.entryList(QDir::Files,QDir::NoSort);
                    }

                    tmpFileList=tmpFileList.filter(Filter);
                        if(tmpFileList.isEmpty()==false)
                        {
                                // Add files path to List
                            QStringList::const_iterator i=tmpFileList.begin();

                            int j=0;

                            while(i!=tmpFileList.end())
                            {
                                if (QFile::exists(dir.path()+"/"+*i))
                                {   
                                     g_File_Pathes.insert(0,dir.path()+"/"+*i);
                                     g_FindByMaskFlag++;
                                }

                            ++i;
                            }
                            j=0;
                        }
                        else{}

                        tmpDirList=dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot,QDir::NoSort);

                        if(tmpDirList.isEmpty()==false)
                        {
                                // Lookup all directories
                                for(qint32 icycle=0x00;icycle<tmpDirList.size();icycle++)
                                {
                                        // Lookup directory
                                        tmpDirList[icycle]=dir.path()+"/"+tmpDirList[icycle];
                                        ScanDir(tmpDirList[icycle],Filter);
                                }
                        }
                        else{}
                }
                else{}
        }
        else{}
}

void HideFiles::ShowByMask(QString dir, QString mask)
{
    QStringList tmp;

    tmp=g_File_Pathes.filter(dir);
    tmp=tmp.filter(mask);

    QStringList::const_iterator i=tmp.begin();

    while(i!=tmp.end())
    {
       g_File_Pathes.removeAt(g_File_Pathes.indexOf(*i));

        ++i;
    }

}

void HideFiles::on_DirMode_stateChanged(int )
{
    if (ui->DirMode->isChecked())
    {
        ui->DirPath->show();
        ui->DirLable->show();
        ui->MaskEdit->show();
        ui->MaskLable->show();
        ui->FilePathLable->hide();
        ui->lineEdit->hide();
        ui->includeDirChbx->setEnabled(true);
    }
    else
    {
        ui->DirPath->hide();
        ui->DirLable->hide();
        ui->MaskEdit->hide();
        ui->MaskLable->hide();
        ui->FilePathLable->show();
        ui->lineEdit->show();
        ui->includeDirChbx->setDisabled(true);;
    }

}

void HideFiles::on_BrowseButton_clicked()
{
    QString fileName;

    if (ui->DirMode->isChecked())
    {
       fileName = QFileDialog::getExistingDirectory(this,
                                                    tr("Select Directory"),
                                                    "/home",
                                                    QFileDialog::ShowDirsOnly
                                                    | QFileDialog::DontResolveSymlinks);
        ui->DirPath->setText(fileName);
    }
    else
    {
        fileName = QFileDialog::getOpenFileName(this,
                                              tr("Select File"),
                                              "/home",
                                              tr("*"));
        ui->lineEdit->setText(fileName);
    }
}

void HideFiles::on_PatheslistView_clicked(QModelIndex index)
{
    QString TmpFilePath;

    if (ui->DirMode->isChecked())
    {
        TmpFilePath=g_File_Pathes.value(index.row());
        TmpFilePath.resize(TmpFilePath.lastIndexOf("/"));
        ui->DirPath->setText(TmpFilePath);

    }
    else
    {
        ui->lineEdit->setText(g_File_Pathes.value(index.row()));
    }
}

int HideFiles::CheckSysFile(QString Path)
{
    QMessageBox WarningMsg;
    WarningMsg.setText("WARNING");
    WarningMsg.setIcon(QMessageBox::Warning);
    WarningMsg.setInformativeText("You realy want to hide files created by system. This can be reason of Kernel Panic");
    WarningMsg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
    WarningMsg.setDefaultButton(QMessageBox::Cancel);
    QFileInfo FileInfo(Path);

    if (FileInfo.groupId()==0)
    {

    int result=WarningMsg.exec();

    switch (result)
        {
        case QMessageBox::Save:

            return 0;

            break;
        case QMessageBox::Ok:

            return 1;

            break;
        default:

            return 0;

            break;
        }
    }
    return 1;
}
